package model

import (
	"fmt"
	"github.com/liushuochen/gotable"
	"gorm.io/gorm"
)

type Host struct {
	Name             string `gorm:"primaryKey"`
	PrivateIP        string `gorm:"not null;index"`
	PublicIP         string `grom:"index"`
	ConnectIP        string `gorm:"not null;index"`
	BastionIP        string
	SSHPort          int    `gorm:"not null; default '22'"`
	SSHUser          string `gorm:"not null; default 'root'"`
	SSHPassword      string
	SSHKeyFile       string
	SSHKeyPassphrase string
	Vendor           string `gorm:"index"`
	Region           string `grom:"index"`
	Project          string `gorm:"index"`
	Env              string `gorm:"index"`
	App              string `gorm:"index"`
}

func (h Host) CheckExist() (bool, error) {
	var c int64
	if err := DB.Where("name = ?", h.Name).Find(&Host{}).Count(&c).Error; err != nil {
		return false, err
	}
	return c > 0, nil
}

func (h Host) Insert() error {
	return DB.Create(&h).Error
}

func (h Host) Update() error {
	return DB.Save(&h).Error
}

func (h Host) InsertOrUpdate() error {
	exist, err := h.CheckExist()
	if err != nil {
		return err
	}
	if exist {
		return h.Update()
	}
	return h.Insert()
}

func QueryHostsForPrint(condition map[string]string) (string, error) {
	hostList, err := QueryHostsByCondition(condition)
	if err != nil {
		return "", err
	}

	var m = make(map[string]string, 6)
	tb, _ := gotable.Create("no", "vendor", "region", "project", "env", "app", "private_ip", "public_ip", "connect_ip", "ssh_user", "ssh_port", "ssh_key_file", "bastion_ip")
	no := 1
	for _, host := range *hostList {
		m = map[string]string{
			"no":           fmt.Sprintf("%d", no),
			"vendor":       host.Vendor,
			"region":       host.Region,
			"project":      host.Project,
			"env":          host.Env,
			"app":          host.App,
			"private_ip":   host.PrivateIP,
			"public_ip":    host.PublicIP,
			"connect_ip":   host.ConnectIP,
			"ssh_user":     host.SSHUser,
			"ssh_port":     fmt.Sprintf("%d", host.SSHPort),
			"ssh_key_file": host.SSHKeyFile,
			"bastion_ip":   host.BastionIP,
		}
		if err := tb.AddRow(m); err != nil {
			return "", err
		}
		no += 1
	}
	tb.OpenBorder()
	return tb.String(), nil
}

func QueryHostsByCondition(condition map[string]string) (*[]Host, error) {
	hostList := make([]Host, 0, 8)
	err := DB.Where(condition).Find(&hostList).Error
	return &hostList, err
}

func QueryHostByCondition(condition map[string]string) (*Host, error) {
	host := Host{}
	err := DB.Where(condition).First(&host).Error
	if err == gorm.ErrRecordNotFound {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	return &host, err
}

func DeleteHostsByCondition(condition map[string]string) error {
	return DB.Where(condition).Delete(&Host{}).Error
}
